from datetime import datetime
from functools import reduce
from random import shuffle

from django.db.models import Q
from django.shortcuts import render
from django.urls import reverse
from django.views import View
from django.http import JsonResponse
from system.models import NavigationModel, NovelModel, Blogroll_Model
from web_api.lib import navigationList, novelSerialize, PaginatorPage


class Navigation(View):
    def get(self, request):
        Nav_List = NavigationModel.objects.order_by('-column_order').filter(is_delete=False).all()
        run_data = lambda x, y: x if y in x else x + [y]
        res = reduce(run_data, [[], ] + navigationList(Nav_List))
        column_display = [dict(o) for o in NavigationModel.objects.order_by('-column_order').filter(is_delete=False, column_display=True).all()]
        return JsonResponse({'code': 0, 'msg': 'success', 'nav_all': res, 'column_display': column_display}, json_dumps_params={'ensure_ascii': False})


class GetNovel(View):
    def get(self, request):
        limit = request.GET.get('limit', 10)
        type = request.GET.get('type', 'newest')  # 默认最新
        try:
            limit = int(limit)
        except:
            limit = 10
        if limit > 100 or limit < 0: limit = 10
        if type == 'hot':
            row_list = NovelModel.objects.order_by('-create_time').order_by('-novel_click').filter(is_delete=False).all()
        elif type == 'random':
            row_list = list(NovelModel.objects.filter(is_delete=False).all())
            shuffle(row_list)
        elif type == 'focus':
            row_list = NovelModel.objects.order_by('-create_time').filter(is_delete=False, novel_is_focus=True).all()
        else:
            row_list = NovelModel.objects.order_by('-create_time').filter(is_delete=False).all()
        dataList = row_list[:limit]
        return JsonResponse({'code': 0, 'dataList': [novelSerialize(d) for d in dataList]})


class NavigationNovel(View):
    def get(self, request):
        nav_list = NavigationModel.objects.order_by('-column_order').filter(is_delete=False, column_index_show=True).all()
        limit = request.GET.get('limit', 6)
        try:
            limit = int(limit)
        except:
            limit = 6  # 默认六条
        if limit > 100 or limit < 0: limit = 6
        dataList = []
        for obj in nav_list:
            nav = dict(obj)
            nav['novelList'] = [dict(n) for n in obj.novel_categories.all()][::-1][:limit]
            for d in nav['novelList']: d.pop('categories')
            dataList.append(nav)
        return JsonResponse({'code': 0, 'navNovel': dataList})


class Links(View):
    def get(self, request):
        links = [dict(b) for b in Blogroll_Model.objects.order_by('-create_time').order_by('-link_sort').filter(is_delete=False, link_end_date__gte=datetime.now()).all()]
        return JsonResponse({'code': 0, 'links': links})


class SortNovel(View):
    def get(self, request):
        uuid = request.GET.get('uid')
        nav = NavigationModel.objects.filter(is_delete=False, uuid=uuid).first()
        novelList = list(nav.novel_categories.all()[::-1])
        data, page = PaginatorPage(request, novelList)
        dataList = [novelSerialize(da, 5) for da in data]
        num = request.GET.get('page', '1')
        try:
            num = int(num)
        except:
            num = 1
        sortData = {'novelList': dataList, 'count': page.count, 'num_pages': page.num_pages, 'page_range': [p for p in page.page_range],
                    'has_next': data.has_next(), 'has_previous': data.has_previous(), 'currentPage': num}
        return JsonResponse({'code': 0, 'data': sortData})


class BookData(View):
    def get(self, request):
        uuid = request.GET.get('book_id')
        try:
            book = NovelModel.objects.filter(is_delete=False, uuid=uuid).first()
        except Exception as e:
            return JsonResponse({'code': 1, 'msg': '参数错误', 'error': str(e)})
        if book:
            try:
                data = novelSerialize(book)
                data['chapter'] = data['chapter'][::-1]
                return JsonResponse({'code': 0, 'bookData': data})
            except Exception as e:
                return JsonResponse({'code': 1, 'msg': '处理异常', 'error': f'[info]：{str(e)}'})
        return JsonResponse({'code': 1, 'msg': '参数错误', 'error': '参数非法'})


class GetOther(View):
    def get(self, request):
        if request.GET.get('cls') == reverse('web_system:rankingList'):  # 排行榜
            novelList = NovelModel.objects.order_by('-novel_click').order_by('-novel_love').order_by('-novel_praise').filter(is_delete=False)
        elif request.GET.get('cls') == reverse('web_system:overList'):  # 完本
            novelList = NovelModel.objects.order_by('-create_time').filter(is_delete=False, novel_state=True)
        elif request.GET.get('cls') == reverse('web_system:serializeList'):  # 连载
            novelList = NovelModel.objects.order_by('-create_time').filter(is_delete=False, novel_state=False)
        else:
            return JsonResponse({'code': 0, 'msg': '超出范围'})
        data, page = PaginatorPage(request, novelList)
        dataList = [novelSerialize(da, 5) for da in data]
        num = request.GET.get('page', '1')
        try:
            num = int(num)
        except:
            num = 1
        sortData = {'novelList': dataList, 'count': page.count, 'num_pages': page.num_pages, 'page_range': [p for p in page.page_range],
                    'has_next': data.has_next(), 'has_previous': data.has_previous(), 'currentPage': num}
        return JsonResponse({'code': 0, 'data': sortData})


class Search(View):
    def get(self, request):
        search_keywords = request.GET.get('keywords', '')
        novelList = NovelModel.objects.filter(
            Q(novel_name__icontains=search_keywords) | Q(novel_author__icontains=search_keywords) | Q(novel_description__icontains=search_keywords) | Q(
                novel_key__icontains=search_keywords))
        data, page = PaginatorPage(request, novelList)
        dataList = [novelSerialize(da, 5) for da in data]
        num = request.GET.get('page', '1')
        try:
            num = int(num)
        except:
            num = 1
        sortData = {'novelList': dataList, 'count': page.count, 'num_pages': page.num_pages, 'page_range': [p for p in page.page_range],
                    'has_next': data.has_next(), 'has_previous': data.has_previous(), 'currentPage': num}
        return JsonResponse({'code': 0, 'data': sortData})
